/*
 * Copyright 2011 Katsunori Koyanagi
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */

package sweezy.core.utils
{
	import flash.utils.Dictionary;

	public class StringUtils
	{

		private static var _esSpecialChars:Dictionary;

		private static var _formatterCache:WeakCache = new WeakCache();

		private static var _xmlEntityChars:Dictionary;

		public static function escapeESString(value:String):String
		{
			if (value === null)
			{
				return "null";
			}

			var result:String = "";
			var len:uint = value.length;
			var index:uint = 0;
			var ch:uint, i:uint;

			for (i = 0; i < len; i++)
			{
				ch = value.charCodeAt(i);
				if (ch in _esSpecialChars)
				{
					if (index !== i)
					{
						result += value.substring(index, i);
					}
					result += _esSpecialChars[ch];
					index = i + 1;
				}
			}
			if (index !== len)
			{
				result += value.substring(index, len);
			}

			return "\"" + result + "\"";
		}

		public static function escapeXMLString(value:String):String
		{
			if (value === null)
			{
				return "";
			}
			if (value.indexOf("&") + value.indexOf("\"") + value.indexOf("\'") + value.indexOf("<") + value.indexOf(">") === -5)
			{
				return value;
			}

			var result:String = "";
			var len:uint = value.length;
			var index:uint = 0;
			var ch:uint, i:uint

			for (i = 0; i < len; i++)
			{
				ch = value.charCodeAt(i);
				if (ch in _xmlEntityChars)
				{
					if (index !== i)
					{
						result += value.substring(index, i);
					}
					result += _xmlEntityChars[ch];
					index = i + 1;
				}
			}
			if (index !== len)
			{
				result += value.substring(index, len);
			}

			return result;
		}

		public static function format(pattern:String, args:Object):String
		{
			if (pattern === null || pattern === "")
			{
				return "";
			}
			if (pattern.indexOf("{") === -1)
			{
				return pattern;
			}

			var formatter:Formatter;
			if (pattern in _formatterCache)
			{
				formatter = _formatterCache[pattern];
			}
			if (formatter === null)
			{
				_formatterCache[pattern] = formatter = new Formatter(pattern);
			}

			return formatter.format(args);
		}

		public static function repeat(str:String, n:uint):String
		{
			if (str === null || str === "" || n === 0)
			{
				return "";
			}

			if (n === 1)
			{
				return str;
			}

			switch (n)
			{
				case 2:
					return str + str;
				case 3:
					return str + str + str;
				case 4:
					return str + str + str + str;
				case 5:
					return str + str + str + str + str;
				case 6:
					return str + str + str + str + str + str;
				case 7:
					return str + str + str + str + str + str + str;
				case 8:
					return str + str + str + str + str + str + str + str;
				case 9:
					return str + str + str + str + str + str + str + str + str;
				case 10:
					return str + str + str + str + str + str + str + str + str + str;
				case 11:
					return str + str + str + str + str + str + str + str + str + str + str;
				case 12:
					return str + str + str + str + str + str + str + str + str + str + str + str;
				case 13:
					return str + str + str + str + str + str + str + str + str + str + str + str + str;
				case 14:
					return str + str + str + str + str + str + str + str + str + str + str + str + str + str;
				case 15:
					return str + str + str + str + str + str + str + str + str + str + str + str + str + str + str;
			}

			var result:String = "";

			for (; n > 0; n >>>= 1, str += str)
			{
				if (n & 1 > 0)
				{
					result += str;
				}
			}

			return result;
		}


		public static function substitute(pattern:String, ... args):String
		{
			return format(pattern, args);
		}

		public static function trim(value:*):String
		{
			if (value === undefined || value === null || value === "")
			{
				return "";
			}

			var str:String = String(value), s:int = 0, e:int = str.length - 1;
			while (0x21 > str.charCodeAt(s))
			{
				++s;
			}
			while (0x21 > str.charCodeAt(e))
			{
				--e;
			}

			return e >= s ? str.slice(s, e + 1) : "";
		}

		{
			_xmlEntityChars = new Dictionary();
			_xmlEntityChars["&".charCodeAt(0)] = "&amp;";
			_xmlEntityChars["<".charCodeAt(0)] = "&lt;";
			_xmlEntityChars[">".charCodeAt(0)] = "&gt;";
			_xmlEntityChars["\"".charCodeAt(0)] = "&quot;";
			_xmlEntityChars["\'".charCodeAt(0)] = "&apos;";

			_esSpecialChars = new Dictionary();
			_esSpecialChars["\"".charCodeAt(0)] = "\\\"";
			_esSpecialChars["\\".charCodeAt(0)] = "\\\\";
			_esSpecialChars["\b".charCodeAt(0)] = "\\b";
			_esSpecialChars["\f".charCodeAt(0)] = "\\f";
			_esSpecialChars["\n".charCodeAt(0)] = "\\n";
			_esSpecialChars["\r".charCodeAt(0)] = "\\r";
			_esSpecialChars["\t".charCodeAt(0)] = "\\t";
		}
	}
}
